package utils

import (
	"context"
	"fpga-vboard/logger"
	"os/exec"
	rt "runtime"

	"github.com/wailsapp/wails/v2/pkg/runtime"
)

type LogStdOutput struct {
	LogInfo *string
	ctx     context.Context
}

func (l *LogStdOutput) Write(p []byte) (n int, err error) {
	*l.LogInfo += string(p)
	runtime.EventsEmit(l.ctx, "cmdoutput", &logger.LogEventMsg{
		Msgtype: logger.MsgTypeInfo,
		Msg:     string(p),
	})
	return len(p), nil
}

type LogErrOutput struct {
	LogInfo *string
	ctx     context.Context
}

func (l *LogErrOutput) Write(p []byte) (n int, err error) {
	*l.LogInfo += string(p)
	runtime.EventsEmit(l.ctx, "cmdoutput", &logger.LogEventMsg{
		Msgtype: logger.MsgTypeError,
		Msg:     string(p),
	})
	return len(p), nil
}

type LogOutput struct {
	StdOut        *LogStdOutput
	StdErr        *LogErrOutput
	CombinLogInfo string
}

var logOutPut *LogOutput

func (l *LogOutput) Clear() {
	l.CombinLogInfo = ""
}

func init() {
	logOutPut = &LogOutput{
		StdOut:        &LogStdOutput{},
		StdErr:        &LogErrOutput{},
		CombinLogInfo: "",
	}
	logOutPut.StdOut.LogInfo = &logOutPut.CombinLogInfo
	logOutPut.StdErr.LogInfo = &logOutPut.CombinLogInfo
}

func SetCtx(ctx context.Context) {
	logOutPut.StdOut.ctx = ctx
	logOutPut.StdErr.ctx = ctx
}

func RunCmdWithParams(path string, cmdstr string) (string, error) {
	// cmds := strings.Split(cmdstr, " ")
	cmdInst := exec.Command("sh", "-c", cmdstr)
	cmdInst.Dir = path
	logOutPut.Clear()
	SetSysProcAttr(cmdInst)
	cmdInst.Stdout = logOutPut.StdOut
	cmdInst.Stderr = logOutPut.StdErr
	err := cmdInst.Run()
	return logOutPut.CombinLogInfo, err
}

func RunCmd(path string, cmd string) (string, error) {
	sh := "sh"
	arg1 := "-c"
	if rt.GOOS == "windows" {
		sh = "cmd"
		arg1 = "/c"
	}
	cmdInst := exec.Command(sh, arg1, cmd)
	cmdInst.Dir = path
	logOutPut.Clear()
	cmdInst.Stdout = logOutPut.StdOut
	cmdInst.Stderr = logOutPut.StdErr
	err := cmdInst.Run()
	return logOutPut.CombinLogInfo, err
}

func RunCmdInCurDir(cmd string) (string, error) {
	sh := "sh"
	arg1 := "-c"
	if rt.GOOS == "windows" {
		sh = "cmd"
		arg1 = "/c"
	}
	cmdInst := exec.Command(sh, arg1, cmd)
	SetSysProcAttr(cmdInst)
	out, err := cmdInst.CombinedOutput()
	return string(out), err
}

func RunCmdInCurDirBackground(cmd string) {
	go func() {
		out, err := RunCmdInCurDir(cmd)
		if err != nil {
			logger.FatalEvent("Run cmd failed. err: %v, out: %s", err, out)
		}
	}()
}
